package utils

import (
	"fmt"
	"log"
	"strings"
)

// 蛇形转驼峰
func ToCamelString(s string) string {
	data := make([]byte, 0, len(s))
	j := false
	k := false
	num := len(s) - 1
	for i := 0; i <= num; i++ {
		d := s[i]
		if k == false && d >= 'A' && d <= 'Z' {
			k = true
		}
		if d >= 'a' && d <= 'z' && (j || k == false) {
			d = d - 32
			j = false
			k = true
		}
		if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' {
			j = true
			continue
		}
		data = append(data, d)
	}
	return string(data[:])
}

func ToSnakeString(s string)string{
	data := make([]byte, 0, len(s))
	uper := false
	num := len(s) - 1
	for i := 0; i <= num; i++ {
		d := s[i]
		if d >= 'A' && d <= 'Z' {
			uper = true
		}
		if(uper){
			if(i != 0){
				data = append(data, '_')
				data = append(data, d + 32)
			}else{
				data = append(data, d + 32)
			}
			uper = false
		}else{
			data = append(data, d)
		}
	}
	return string(data)
}

type FieldDesc struct {
	FiledName string `json:"field_name"`
	Type      string `json:"type"`
	Primary   bool   `json:"primary"`
}

func DDLType2Golang(types string)string{
	if strings.Contains(types,"int"){
		return "int32"
	}
	if strings.Contains(types,"varchar"){
		return "string"
	}
	if strings.Contains(types,"longblob"){
		return "[]byte"
	}
	if strings.Contains(types,"date"){
		return "time.Time"
	}
	return "interface"
}

func CreateGoStruct(name string,doc []FieldDesc) string{
	if name == "" {
		return ""
	}
	if len(doc) == 0{
		return ""
	}
	ret := fmt.Sprintf("golang gorm tag struct 代码:\r\ntype %s struct{\r\n",ToCamelString(name))
	for _,v := range doc{
		filed := "\t\t"
		camelField := ToCamelString(v.FiledName)
		filed += camelField  
		tag := fmt.Sprintf("`json:\"%s\" gorm:\"column:%s\" sql:\"%s\"`",v.FiledName,v.FiledName,v.FiledName)
		filed += " " + DDLType2Golang(v.Type)  + " " + tag + " \r\n"
		ret += filed
	}
	ret += "}"
	return ret
}


func CreateMarkdownTable(name string,doc []FieldDesc) string{
	if name == "" {
		return ""
	}
	if len(doc) == 0{
		return ""
	}
	ret := fmt.Sprintf("数据表 %s markdown 表格字段说明： \r\n",ToCamelString(name))
	ret += "|字段名称|字段类型|字段说明|是否主键| \r\n|-|-|-|-| \r\n"
	for _,v := range doc{
		ret += fmt.Sprintf("|%s|%s||%t|\r\n",v.FiledName,v.Type,v.Primary)
	}
	return ret
}

func TrimUnWanted(in string) string {
	ret := strings.ReplaceAll(in, "\t","")
	ret = strings.ReplaceAll(ret, "\n","")
	ret = strings.ReplaceAll(ret, "\x09","")
	ret = strings.ReplaceAll(ret, "\r","")
	ret = strings.ReplaceAll(ret, "\x0a","")
	ret = strings.TrimLeft(ret," ")
	return ret
}

func DDL2Field(ddl string) (string, []FieldDesc) {
	if "" == ddl {
		return "", nil
	}
	ret := make([]FieldDesc, 0)
	ddl = strings.ReplaceAll(ddl,"`","")
	log.Print(ddl)
	indexStart := strings.Index(ddl, "CREATE TABLE")
	indexFirstParentheses := strings.Index(ddl, "(")
	indexLastParentheses := strings.LastIndex(ddl, ")")

	sTbNameUnTrim := ddl[indexStart+len("CREATE TABLE") : indexFirstParentheses]
	sTableName := strings.Trim(sTbNameUnTrim, " ")

	sTbDesc := ddl[indexFirstParentheses+1 : indexLastParentheses]
	fields := strings.Split(sTbDesc, "\n")
	
	primarykey := []string{}
	for _, v := range fields {
		if strings.Contains(v, "PRIMARY KEY") {
			start := strings.Index(v, "(")
			end := strings.LastIndex(v, ")")
			primarykey = append(primarykey, v[start+1:end])
		} else {
			v = TrimUnWanted(v)
			log.Print(v)
			tmp := strings.Split(v, " ")
			if len(tmp) > 1 {
				log.Print(tmp[0])
				ret = append(ret, FieldDesc{
					FiledName: TrimUnWanted(tmp[0]),
					Type:     strings.Trim(tmp[1], " "),
					Primary:   false,
				})
			}
		}
	}
	for _, key := range primarykey {
		for k := range ret {
			if 0 == strings.Compare(ret[k].FiledName, key) {
				ret[k].Primary = true
			}
		}
	}
	return sTableName, ret
}
